package xkp.lesson3;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Server {
    public static void main(String[] args) throws IOException {
        List<SocketChannel> socketChannels = new ArrayList<>();
        //首先开启ServerSocketChannel管道,服务端通道相当于ServerSocket等待客户端连接
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //配置管道为非阻塞
        serverSocketChannel.configureBlocking(false);
        //监听端口
        serverSocketChannel.bind(new InetSocketAddress(8888));
        //开启选择器
        Selector selector = Selector.open();
        //注册管道到选择器
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while(true) {
            //等待事件到来
            selector.select();
            Iterator<SelectionKey> iterator =  selector.selectedKeys().iterator();
            //c语言中也有NIO  也有selector
            //数量掌握Selector(NIO)
            while(iterator.hasNext()) {
                SelectionKey key = iterator.next();
                if(key.isAcceptable()) {
                    ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = channel.accept();
                    socketChannels.add(socketChannel);
                    System.out.println(socketChannel.getRemoteAddress()+":连接成功");
                    //把客户端通道也给配置为非阻塞
                    socketChannel.configureBlocking(false);
                    //继续把客户端也给注册到selector中
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }else if(key.isReadable()) {
                    //单独获取客户端chinnel
                    SocketChannel channel =  (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    //从channel中读取数据，写入buffer中
                    channel.read(buffer);
                    //写模式转换为读模式
                    buffer.flip();
                    //转发给所有人
                    for(SocketChannel socketChannel:socketChannels) {
                        socketChannel.write(buffer);
                        //重置postion和limit
                        buffer.flip();
                    }
                }
                iterator.remove();
            }
        }
    }
}
